/*=============================================================================
*
*   Copyright (C) 2020 All rights reserved.
*
*   Filename:		test_crack.cpp
*
*   Author: Wang Zhecheng - wangzhecheng@yeah.net
*
*   Date: 2020-02-20 21:23
*
*   Last Editors: Wang Zhecheng - wangzhecheng@yeah.net
*
*   Last modified:	2020-08-31 04:35
*
*   Description:
*
=============================================================================*/
#define BOOST_AUTO_TEST_MAIN test_crack

#include "../../include/biot.hpp"
#include "../../include/fem.hpp"
#include "../../include/geometry/shape/subdivide.hpp"
#include "../../include/implicit_solver.hpp"
#include "../../include/incremental_load.hpp"
#include "../../include/io/data_extractor.hpp"
#include "../../include/io/vtu_writer.hpp"
#include "../../include/model/model.hpp"
#include "../../include/static_equation.hpp"
#include "../../include/xfem/levelset.hpp"
#include <boost/geometry.hpp>
#include <boost/test/included/unit_test.hpp>

LOGGING_REGISTER()

BOOST_AUTO_TEST_CASE(geometry_test) {

  using namespace geoxfem;

  using MethodPolicy   = model::fem;
  using CouplePolicy   = model::biot;
  using DimensionType  = geometry::plane_strain;
  using EquationPolicy = model::static_equation;
  using SolvePolicy    = model::implicit_solver;
  using LoadPolicy     = model::incremental_load;
  using Model =
    geoxfem::model::Model<MethodPolicy, CouplePolicy, DimensionType,
                          EquationPolicy, SolvePolicy, LoadPolicy, mpl1>;

  using Shape = geometry::ShapeInterface<DimensionType, mpl1>;
  using Gauss = model::GaussPoint<DimensionType>;
  /* using Segment = geometry::Segment<DimensionType, mpl1>; */

  Model model;

  std::string input_file_name =
    (boost::unit_test::framework::master_test_suite().argc < 2)
      ? "test/test_crack/crack.json"
      : boost::unit_test::framework::master_test_suite().argv[1];

  /*  detail, trace, process, info, warning, debug, error }; */
  geoxfem::log::log_init(geoxfem::log::severity_level::error);

  io::DataParser<io::json> parser;
  parser.read(input_file_name);

  model.init(parser);
  model.buildProblem();

  BOOST_CHECK_CLOSE(algorithm::integral(*model.getMesh(),
                                        [](const Shape&, const Gauss&) {
                                          return static_cast<_real>(1);
                                        }),
                    16, 1);

  /* bool if_plot = (boost::unit_test::framework::master_test_suite().argc < 3)
   */
  /*                  ? true */
  /*                  : std::stoi(std::string( */
  /*                    boost::unit_test::framework::master_test_suite().argv[2]));
   */

  geometry::Point<2> p1(0, -2);
  geometry::Point<2> p2(0, 2);
  auto [psi_p1_tip1_before, phi_p1_tip1_before] =
    xfem::GetLevelSet(p1, model.getCrack(0).getHeadTip());
  auto [psi_p1_tip2_before, phi_p1_tip2_before] =
    xfem::GetLevelSet(p1, model.getCrack(0).getTailTip());
  auto [psi_p2_tip1_before, phi_p2_tip1_before] =
    xfem::GetLevelSet(p2, model.getCrack(0).getHeadTip());
  auto [psi_p2_tip2_before, phi_p2_tip2_before] =
    xfem::GetLevelSet(p2, model.getCrack(0).getTailTip());
  BOOST_CHECK_CLOSE(psi_p1_tip1_before, -2.11803398875, 1e-1);
  BOOST_CHECK_CLOSE(phi_p1_tip1_before, -2.5, 1e-1);
  BOOST_CHECK_CLOSE(psi_p1_tip2_before, -1, 1e-1);
  BOOST_CHECK_CLOSE(phi_p1_tip2_before, -2.5, 1e-1);
  BOOST_CHECK_CLOSE(psi_p2_tip1_before, -2.11803398875, 1e-1);
  BOOST_CHECK_CLOSE(phi_p2_tip1_before, 1.5, 1e-1);
  BOOST_CHECK_CLOSE(psi_p2_tip2_before, -1, 1e-1);
  BOOST_CHECK_CLOSE(phi_p2_tip2_before, 1.5, 1e-1);

  auto tip = model.getCrack(0).getTailTip();
  xfem::propagate(-M_PI_2, 1, model, *tip);

  /* BOOST_CHECK_CLOSE(algorithm::integral<Model::Mesh>::apply<_real>( */
  /*                     *model.getMesh(), [](const Gauss&) { return 1; }), */
  /*                   16, 1); */

  auto [psi_p1_tip1_after, phi_p1_tip1_after] =
    xfem::GetLevelSet(p1, model.getCrack(0).getHeadTip());
  auto [psi_p1_tip2_after, phi_p1_tip2_after] =
    xfem::GetLevelSet(p1, model.getCrack(0).getTailTip());
  auto [psi_p2_tip1_after, phi_p2_tip1_after] =
    xfem::GetLevelSet(p2, model.getCrack(0).getHeadTip());
  auto [psi_p2_tip2_after, phi_p2_tip2_after] =
    xfem::GetLevelSet(p2, model.getCrack(0).getTailTip());
  BOOST_CHECK_CLOSE(psi_p1_tip1_after, -2.11803398875, 1e-1);
  BOOST_CHECK_CLOSE(phi_p1_tip1_after, -2.5, 1e-1);
  BOOST_CHECK_CLOSE(psi_p1_tip2_after, -2, 1e-1);
  BOOST_CHECK_CLOSE(phi_p1_tip2_after, -2.5, 1e-1);
  BOOST_CHECK_CLOSE(psi_p2_tip1_after, -4.11803398875, 1e-1);
  BOOST_CHECK_CLOSE(phi_p2_tip1_after, 1.11803398875, 1e-1);
  BOOST_CHECK_CLOSE(psi_p2_tip2_after, 0.5, 1e-1);
  BOOST_CHECK_CLOSE(phi_p2_tip2_after, -1, 1e-1);

  if(false) {
    io::DataPloter ploter;
    model.plot(ploter);
    /* ploter.appendSetting("set xrange [-2:-0.8]"); */
    /* ploter.appendSetting("set yrange [0.2:0.9]"); */
  }
}
